import os
import json
import hashlib
import shutil
import zipfile
import logging
from datetime import datetime

def md5(filename):
	fp = open(filename, 'rb')
	fc = fp.read()
	fp.close()
	file_md5 = hashlib.md5(fc)
	return file_md5.hexdigest()

def writeVerFile(path, jsonobj):
    logging.info('写入版本数据库...')
    fp = open(path, 'w')
    json.dump(jsonobj, fp, sort_keys=True, indent=4)
    fp.close()
    logging.info('写入版本数据库成功!')

def readVerFile(path):
    logging.info('读取版本数据库...')
    if os.path.isfile(path):
        fp = open(path, "r")
        filesmd5 = json.load(fp)
        fp.close()
        return filesmd5
    else:
        logging.error('读取版本数据库失败！')

def diskwalk(path):
    files = []
    for dirpath, _, filenames in os.walk(path):
        for filename in filenames:
            fullpath = os.path.join(dirpath, filename)
            files.append(fullpath)
    return files

def copyfiles(srcdir, dstdir, abspath):
    src = abspath
    dst = os.path.join(dstdir, abspath.replace(srcdir, ""))
    dir = os.path.dirname(dst)
    if not os.path.exists(dir) :
        logging.info('目录%s不存在，创建目录.' % (dir))
        os.makedirs(dir)
    shutil.copyfile(src, dst)
    logging.info('拷贝文件%s到%s' % (src, dst))

def getfilesize(filename):
    fsize = os.path.getsize(filename)
    fsize = fsize / float(1024)
    return round(fsize, 2)

def archiveAll(apath, tpath):
    filesize = 0
    count = 1
    fp = zipfile.ZipFile(os.path.join(apath, "archive%02d.zip" % count), "w")
    for filename in diskwalk(tpath):
        filesize += getfilesize(filename)
        logging.info("压缩%s[%0.2fk]" % (filename, filesize))

        if fp == 0:
            fp = zipfile.ZipFile(os.path.join(apath, "archive%02d.zip" % count), "w")

        fp.write(filename, filename.replace(apath, ""))
        if filesize > 5:
            count += 1
            fp.close()
            fp = 0
    if fp:
        fp.close()

def checkdiff(input, output):
    timestr = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    veriondir = os.path.join(output, timestr)
    if not os.path.exists(veriondir):
        os.makedirs(veriondir)
    archivedir = os.path.join(veriondir, "archive")
    if not os.path.exists(archivedir):
        os.makedirs(archivedir)

    logging.basicConfig(filename=os.path.join(veriondir, 'log.txt'), filemode='w', level=logging.DEBUG)

    if not os.path.exists(input):
        logging.error('指定目录%s不存在！' % input)
        return

    verfile = os.path.join(output, 'version.json')

    copyfiles(output, veriondir, verfile)

    historymd5 = readVerFile(verfile)
    if historymd5 :
        logging.info('数据库记录就绪，开始差异对比...')
        filesmd5 = {}
        for filename in diskwalk(input):
            md5str = md5(filename)
            filesmd5[filename] = md5str
            if historymd5.get(filename):
                if historymd5[filename] != md5str :
                    logging.info('[modify]%s -> %s' % (filename, md5str))
                    copyfiles(input, archivedir, filename)
                else:
                    logging.info('[unchange]%s -> %s' %(filename, md5str))
            else:
                logging.info('[add]%s -> %s' %(filename, md5str))
                copyfiles(input, archivedir, filename)
        writeVerFile(verfile, filesmd5)
        archiveAll(veriondir, archivedir)
    else:
        logging.info('无数据库记录，建立档案...')
        filesmd5 = {}
        for filename in diskwalk(input):
            md5str = md5(filename)
            filesmd5[filename] = md5str
            logging.info('[add]%s -> %s' %(filename, md5str))
        writeVerFile(verfile, filesmd5)


input = "/Volumes/MacintoshHD/DevProject/"
output = "/Volumes/MacintoshHD/HotUpdate/"
checkdiff(input, output)